﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace SPMS.Common
{
    /// <summary>
    /// 权限检查特性，用于检查登录用户的所属角色和用户。
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class PermissionRequirementsAttribute : ActionFilterAttribute
    {
        #region ---Constructor

        /// <summary>
        /// 初始化类型<see cref="PermissionRequirementsAttribute" />的新实例。
        /// </summary>
        protected PermissionRequirementsAttribute()
            : base()
        {
        }

        /// <summary>
        /// 初始化类型<see cref="PermissionRequirementsAttribute" />的新实例。
        /// </summary>
        /// <param name="functionalities">要求的功能列表。</param>
        public PermissionRequirementsAttribute(params int[] functionalities)
            : base()
        {
            //创建权限要求
            this.m_Requirement = new GenericFunctionalityRequirement(functionalities);
        }

        /// <summary>
        /// 初始化类型<see cref="PermissionRequirementsAttribute" />的新实例。
        /// </summary>
        /// <param name="roles">需要的角色列表。</param>
        public PermissionRequirementsAttribute(params string[] roles)
            : base()
        {
            //创建权限要求
            this.m_Requirement = new GenericRoleRequirement(roles);
        }

        /// <summary>
        /// 初始化类型<see cref="PermissionRequirementsAttribute" />的新实例。
        /// </summary>
        /// <param name="functionalities">要求的功能列表。</param>
        /// <param name="roles">需要的角色列表。</param>
        public PermissionRequirementsAttribute(int[] functionalities, string[] roles)
            : base()
        {
            //创建权限要求
            this.m_Requirement = new CompositionPermissionRequirement(new GenericFunctionalityRequirement(functionalities), new GenericRoleRequirement(roles), CompositionRelationship.Or);
        }

        /// <summary>
        /// 初始化类型<see cref="PermissionRequirementsAttribute" />的新实例。
        /// </summary>
        /// <param name="requirement">权限要求。</param>
        /// <exception cref="System.ArgumentNullException">当<see cref="requirement"/>为<c>null</c>时，抛出此异常。</exception>
        public PermissionRequirementsAttribute(IPermissionRequirement requirement)
            : base()
        {
            //判断参数
            if (null == requirement)
            {
                //抛出异常
                throw new ArgumentNullException("requirement");
            }

            //保存参数
            this.m_Requirement = requirement;
        }

        #endregion

        #region ---Public Method

        /// <summary>
        /// 当Action准备执行时促发。
        /// </summary>
        /// <param name="filterContext">上下文。</param>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2012/03/09 11:04    创建
        /// </history>
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //判定是否已经登录
            if (filterContext.HttpContext.Request.IsAuthenticated)
            {
                //获得当前主体
                var principal = FormsAuthenticationHelper.GetCurrentPrincipal();

                //判断是否具有权限
                if (!this.m_Requirement.IsValid(principal))
                {
                    //抛出尚未授权异常
                    throw new UnauthorizedException();
                }
            }
            else
            {
                //抛出尚未认证异常
                throw new UnauthenticatedException();
            }
        }

        #endregion

        #region ---Property

        /// <summary>
        /// 获得权限要求。
        /// </summary>
        /// <value>
        /// 权限要求。
        /// </value>
        public IPermissionRequirement Requirement
        {
            get
            {
                return this.m_Requirement;
            }
        }

        #endregion

        #region ---Field

        /// <summary>
        /// 权限要求。
        /// </summary>
        private IPermissionRequirement m_Requirement;

        #endregion
    }
}
